package com.ruoyi.folder.config;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@Component
public class AliyunOSSUtils {
    @Autowired
    private AliyunOSSProp aliyunOSSProp;

    /**
     * 上传文件
     *
     * @return 文件上传后的路径
     */
    public String putObject(File file) {
// 指定文件上传的文件完整路径。路径中不能包含Bucket名称，例如2024/02/06/abc.jpg
        LocalDate localDate = LocalDate.now();
        String dir = localDate.getYear() + "/" + localDate.getMonthValue() + "/"
                + localDate.getDayOfMonth();
        String objectName = dir + "/" + IdUtil.simpleUUID() + "." +
                FileUtil.extName(file);
        if (ObjectUtil.isNotEmpty(aliyunOSSProp.getFilePath())) {
            objectName = aliyunOSSProp.getFilePath() + "/" + objectName;
        }
// 创建OSSClient实例。
        OSS ossClient = new
                OSSClientBuilder().build(aliyunOSSProp.getEndpoint(),
                aliyunOSSProp.getAccessKey(), aliyunOSSProp.getAccessKeySecret());
// 创建PutObjectRequest对象。 ，
        PutObjectRequest putObjectRequest = new
                PutObjectRequest(aliyunOSSProp.getBucketName(), objectName, file);
// 上传文件。
        PutObjectResult result = ossClient.putObject(putObjectRequest);
// 关闭OSSClient。
        ossClient.shutdown();
// 返回文件上传后的路径
        String filePath = "https://" + aliyunOSSProp.getBucketName() + "." +
                aliyunOSSProp.getEndpoint() + "/" + objectName;
        return filePath;
    }

    public String putObject(InputStream is, String fileName) {
// 指定文件上传的文件完整路径。路径中不能包含Bucket名称，例如image/abc.jpg
        LocalDate localDate = LocalDate.now();
        String dir = localDate.getYear() + "/" + localDate.getMonthValue() + "/"
                + localDate.getDayOfMonth();
        String objectName = dir + "/" + IdUtil.simpleUUID() + "." +
                FileUtil.extName(fileName);
        if (ObjectUtil.isNotEmpty(aliyunOSSProp.getFilePath())) {
            objectName = aliyunOSSProp.getFilePath() + "/" + objectName;
        }
// 创建OSSClient实例。
        OSS ossClient = new
                OSSClientBuilder().build(aliyunOSSProp.getEndpoint(),
                aliyunOSSProp.getAccessKey(), aliyunOSSProp.getAccessKeySecret());
// 创建PutObjectRequest对象。 ，
        PutObjectRequest putObjectRequest = new
                PutObjectRequest(aliyunOSSProp.getBucketName(), objectName, is);
// 上传文件。
        PutObjectResult result = ossClient.putObject(putObjectRequest);
// 关闭OSSClient。
        ossClient.shutdown();
// 返回文件上传后的路径
        String filePath = "https://" + aliyunOSSProp.getBucketName() + "." +
                aliyunOSSProp.getEndpoint() + "/" + objectName;
        return filePath;
    }

    /**
     * 获取oss签名及其他信息
     *
     * @return
     */
    public Map<String, String> getOssSign() {
//1.指定上传的位置。格式为 bucketname.endpoint
        String host = "https://" + aliyunOSSProp.getBucketName() + "." +
                aliyunOSSProp.getEndpoint();
//2.指定文件上传的文件夹。
        LocalDate localDate = LocalDate.now();
        String dir = localDate.getYear() + "/" + localDate.getMonth() + "/" +
                localDate.getDayOfMonth();
//3.创建OSSClient实例。
        OSS ossClient = null;
        try {
//4.策略过期时间
            long expireTime = 100;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
//5.PostObject请求最大可支持的文件大小为5 GB，即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0,
                    1048576000);
            policyConds.addConditionItem(MatchMode.StartWith,
                    PolicyConditions.COND_KEY, dir);
//6.创建OSSClient实例。
            ossClient = new OSSClientBuilder()
                    .build(aliyunOSSProp.getEndpoint(),
                            aliyunOSSProp.getAccessKey(), aliyunOSSProp.getAccessKeySecret());
            String postPolicy = ossClient.generatePostPolicy(expiration,
                    policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
//7.签名
            String postSignature = ossClient.calculatePostSignature(postPolicy);
//8.返回签名及OSS相关参数
            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", aliyunOSSProp.getAccessKey());
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            return respMap;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }
}